
// This version of PageStates uses a singly-linked list to store
// page objects.  This will use a little more memory than
// the VarStore version, but will be much more efficient
// with traversals (this.dump()).
function PageStates()
{
	this.compress = false;
	this.isDirty = PageStatesIsDirty;
	
	this.head = null;
	this.dirty = false;

	this.setPage = PageStatesSetPage;
	this.resetPage = PageStatesResetPage;
	this.getPageState = PageStatesGetState;
	this.dump = PageStatesDump;
	this.load = PageStatesLoad;
	this.clear = PageStatesClear;
	this.clearRec = PageStatesClearRec;
	
	return this;
}

function PageStatesSetPage(obj_page)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objPage = new Page(obj_page.section,obj_page.topic,obj_page.subtopic,obj_page.page);

	if (this.head == null)
	{
		this.head = objPage;
		this.head.next = null;
		this.dirty = true;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist do nothing and return immediately.
			if (objPage.toString() == nextNode.toString())
			{
				return;
			}
			// If objPage > nextNode, move to next node and repeat.
			if (objPage.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				// We've reached the location in the list
				// where objPage belongs, so go ahead
				// and splice it in.
				this.dirty = true;
				objPage.next = nextNode;
				if (prevNode == nextNode) // if initially only one node.
				{
					this.head = objPage;
				}
				else
				{
					prevNode.next = objPage;
				}
				return;
			}
		}
		// We've reached the end.
		this.dirty = true;
		prevNode.next = objPage;
		objPage.next = null;
	}
}

function PageStatesResetPage(obj_page)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objPage = new Page(obj_page.section,obj_page.topic,obj_page.subtopic,obj_page.page);
	
	// If list is empty, simply return.
	if (this.head == null)
	{
		return;
	}
	else if (this.head.toString() == objPage.toString())
	{
		this.head = this.head.next;
		return;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist then remove it and return immediately.
			if (objPage.toString() == nextNode.toString())
			{
				// The operation below will remove the reference
				// to nextNode, effectively deleting it from memory
				// through garbage collection.
				prevNode.next = nextNode.next;
				this.dirty = true;
				return;
			}
			// If objPage > nextNode, move to next node and repeat.
			if (objPage.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				return;
			}
		}
	}
}

function PageStatesGetState(obj_page)
{
	var prevNode = this.head;
	var nextNode = this.head;
	var objPage = new Page(obj_page.section,obj_page.topic,obj_page.subtopic,obj_page.page);
	
	// If list is empty, simply return false.
	if (this.head == null)
	{
		return false;
	}
	else
	{
		while (nextNode != null)
		{
			// If node already exist then return true.
			if (objPage.toString() == nextNode.toString())
			{
				return true;
			}
			// If objPage > nextNode, move to next node and repeat.
			if (objPage.toString() > nextNode.toString())
			{
				prevNode = nextNode;
				nextNode = nextNode.next;
			}
			else
			{
				return false;
			}
		}
	}
	return false;
}


function PageStatesDump()
{
	var temp = "";
	var currSection, currTopic, currSubtopic;
	currSection = currTopic = currSubtopic = null;

	var nextNode = this.head;
	while (nextNode != null)
	{
		if (nextNode.section == currSection && nextNode.topic == currTopic && nextNode.subtopic == currSubtopic)
		{
			temp += "," + nextNode.page;
		}
		else
		{
			currSection = nextNode.section;
			currTopic = nextNode.topic;
			currSubtopic = nextNode.subtopic;
			temp += "S" + currSection + "T" + currTopic + "U" + currSubtopic + "P" + nextNode.page;
		}
		nextNode = nextNode.next;
	}
	this.dirty = false;
	if (this.compress)
	{
		return compressUnicodeString(temp);
	}
	else
	{
		return temp;
	}
}

function PageStatesLoad(dataString)
{
	if (this.compress)
	{
		dataString = uncompressUnicodeString(dataString);
	}

	var beenThereArray = dataString.split("S");
	
	for (var i=1;i<beenThereArray.length;i++)
	{
		var index = null;
		var section, topic, subtopic
		var pageArray = null;
		
		index = beenThereArray[i].indexOf("T");
		section = parseInt(beenThereArray[i].slice(0,index));
		beenThereArray[i] = beenThereArray[i].slice(index+1,beenThereArray[i].length);

		index = beenThereArray[i].indexOf("U");
		topic = parseInt(beenThereArray[i].slice(0,index));
		beenThereArray[i] = beenThereArray[i].slice(index+1,beenThereArray[i].length);

		index = beenThereArray[i].indexOf("P");
		subtopic = parseInt(beenThereArray[i].slice(0,index));
		beenThereArray[i] = beenThereArray[i].slice(index+1,beenThereArray[i].length);
		
		pageArray = beenThereArray[i].split(",");
		for (var t=0;t<pageArray.length;t++)
		{
			this.setPage(new Page(section, topic, subtopic, parseInt(pageArray[t])));
		}
	}
}

function PageStatesClear()
{
	this.clearRec(this.head);
	this.head = null;
}

function PageStatesClearRec(nodeRef)
{
	if (nodeRef != null)
	{
		this.clearRec(nodeRef.next);
		nodeRef.next = null;
	}
}

function PageStatesIsDirty()
{
	return this.dirty;
}
